import { useUserStore } from '@/stores'
import router from '@/router'
import axios, { type Method } from 'axios'
// import type { Method } from 'axios'
import { showToast } from 'vant'
import { RouteName } from '@/enums'

const baseURL = 'https://consult-api.itheima.net/'

// 1. 新axios实例，基础配置
const instance = axios.create({
  baseURL,
  timeout: 10000,
})

// 2. 请求拦截器，携带token
instance.interceptors.request.use(
  (config) => {
    const store = useUserStore()
    if (store.user?.token && config.headers) {
      config.headers['Authorization'] = `Bearer ${store.user?.token}`
    }
    return config
  },
  (err) => Promise.reject(err)
)

// 3. 响应拦截器，剥离无效数据，401拦截
instance.interceptors.response.use(
  (res) => {
    // 后台约定，响应成功，但是code不是10000，是业务逻辑失败
    if (res.data?.code !== 10000) {
      showToast(res.data?.message || '业务失败')
      return Promise.reject(res.data)
    }
    // 业务逻辑成功，返回响应数据，作为axios成功的结果
    return res.data
  },
  (err) => {
    if (err.response.status === 401) {
      // 删除用户信息
      const store = useUserStore()
      store.delUser()
      // 跳转登录，带上接口失效所在页面的地址，登录完成后回跳使用
      router.push({
        name: RouteName.login,
        query: { returnUrl: router.currentRoute.value.fullPath },
      })
    }
    return Promise.reject(err)
  }
)

type MyResponse<T> = {
  code: number
  data: T
  message: string
}

// 把请求参数封装成一个对象类型，这样有两个好处：
// 1. 传参没有顺序问题（可选参数）
// 2. 更符合原生 axiosInstance.reqeust 方法的调用习惯
type RequestArgs = {
  method?: Method
  url: string
  data?: object
}

const request = <T>(args: RequestArgs) => {
  const { method = 'GET', url, data } = args
  // 我们现在的问题是：由于响应拦截器中已经剥离了 res.data，所以 instance.request 函数的返回值类型不能是默认的 AxiosResponse<T> 了，所以需要改变 instance.request 的返回值类型；
  // 那如何修改 instance.request 的返回值类型呢？  传第二个泛型参数即可
  // 那问题又来了：由于是第二个泛型参数，不能跳过第一个直接传第二个（语法通不过），所以第一个泛型参数也必须要传一个占个位置（可以随便传，那就传个 any）
  return instance.request<any, MyResponse<T>>({
    method,
    url,
    [method.toUpperCase() === 'GET' ? 'params' : 'data']: data,
    // 如果是 GET 请求，请求参数是用 params 传的，不是 data
    // 如果是其他类型的请求，才是 data
  })
}

export { baseURL, instance, request }
